﻿// SKNotes - a note taking and gathering tool
// Copyright (C) 2009  Stefan Kueng
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.Samples.CustomControls;

namespace SKNotes.CustomControls.HtmlEditor.Control
{
    /// <summary>
    /// Interaction logic for HtmlEditorMenu.xaml
    /// </summary>
    public partial class EditorMenu : UserControl
    {

        public static readonly RoutedEvent FontSelectionChangedEvent;
        public static readonly RoutedEvent FontSizeSelectionChangedEvent;
        public static readonly RoutedEvent FontColourSelectedEvent;
        public static readonly RoutedEvent HighlightColourSelectedEvent;
        public static readonly RoutedEvent StrikeThroughSelectedEvent;
        public static readonly RoutedEvent AnchorInsertingEvent;
        public static readonly RoutedEvent AnchorInsertedEvent;

        public static readonly DependencyProperty FontColourProperty;
        public static readonly DependencyProperty HighlightColourProperty;

        static EditorMenu()
        {
            FontSelectionChangedEvent = EventManager.RegisterRoutedEvent("FontSelectionChanged", RoutingStrategy.Bubble,
                typeof(FontSelectionEventHandler), typeof(EditorMenu));
            FontSizeSelectionChangedEvent = EventManager.RegisterRoutedEvent("FontSizeSelectionChanged", RoutingStrategy.Bubble,
                typeof(FontSelectionEventHandler), typeof(EditorMenu));
            FontColourSelectedEvent = EventManager.RegisterRoutedEvent("FontColourSelected", RoutingStrategy.Bubble,
                typeof(RoutedEventHandler), typeof(EditorMenu));
            HighlightColourSelectedEvent = EventManager.RegisterRoutedEvent("HighlightColourSelected", RoutingStrategy.Bubble,
                typeof(RoutedEventHandler), typeof(EditorMenu));
            StrikeThroughSelectedEvent = EventManager.RegisterRoutedEvent("StrikeThroughSelected", RoutingStrategy.Bubble,
                typeof(RoutedEventHandler), typeof(EditorMenu));
            AnchorInsertingEvent = EventManager.RegisterRoutedEvent("AnchorInserting", RoutingStrategy.Bubble,
                typeof(AnchorEventHandler), typeof(EditorMenu));
            AnchorInsertedEvent = EventManager.RegisterRoutedEvent("AnchorInserted", RoutingStrategy.Bubble,
                typeof(AnchorEventHandler), typeof(EditorMenu));

            FontColourProperty = DependencyProperty.Register("FontColour", typeof(Color),
                typeof(EditorMenu), new PropertyMetadata(Colors.Black));
            HighlightColourProperty = DependencyProperty.Register("HighlightColour", typeof(Color),
                typeof(EditorMenu), new PropertyMetadata(Colors.White));
        }

        /// <summary>
        /// Raised when a font is selected.
        /// </summary>
        public event FontSelectionEventHandler FontSelectionChanged
        {
            add { AddHandler(FontSelectionChangedEvent, value); }
            remove { RemoveHandler(FontSelectionChangedEvent, value); }
        }

        /// <summary>
        /// Raised when the font size is changed.
        /// </summary>
        public event FontSelectionEventHandler FontSizeSelectionChanged
        {
            add { AddHandler(FontSizeSelectionChangedEvent, value); }
            remove { RemoveHandler(FontSizeSelectionChangedEvent, value); }
        }

        /// <summary>
        /// Raised when a font colour is selected.
        /// </summary>
        public event RoutedEventHandler FontColourSelected
        {
            add { AddHandler(FontColourSelectedEvent, value); }
            remove { RemoveHandler(FontColourSelectedEvent, value); }
        }

        /// <summary>
        /// Raised when a highlight colour is selected.
        /// </summary>
        public event RoutedEventHandler HighlightColourSelected
        {
            add { AddHandler(HighlightColourSelectedEvent, value); }
            remove { RemoveHandler(HighlightColourSelectedEvent, value); }
        }

        /// <summary>
        /// Raised when the strikethough text option is selected.
        /// </summary>
        public event RoutedEventHandler StrikeThoughSelected
        {
            add { AddHandler(StrikeThroughSelectedEvent, value); }
            remove { RemoveHandler(StrikeThroughSelectedEvent, value); }
        }

        /// <summary>
        /// Raised when an anchor is being inserted.
        /// </summary>
        public event AnchorEventHandler AnchorInserting
        {
            add { AddHandler(AnchorInsertingEvent, value); }
            remove { RemoveHandler(AnchorInsertingEvent, value); }
        }

        /// <summary>
        /// Raised when an anchor is inserted.
        /// </summary>
        public event AnchorEventHandler AnchorInserted
        {
            add { AddHandler(AnchorInsertedEvent, value); }
            remove { RemoveHandler(AnchorInsertedEvent, value); }
        }

        /// <summary>
        /// Get or Set the font colour.
        /// </summary>
        public Color FontColour
        {
            get { return (Color)this.GetValue(FontColourProperty); }
            set { this.SetValue(FontColourProperty, value); }
        }

        /// <summary>
        /// Get or Set the highlight colour.
        /// </summary>
        public Color HighlightColour
        {
            get { return (Color)this.GetValue(HighlightColourProperty); }
            set { this.SetValue(HighlightColourProperty, value); }
        }

        public EditorMenu()
        {
            InitializeComponent();
            this.cboFontName.ItemsSource = Fonts.SystemFontFamilies;
            this.cboFontSize.ItemsSource = Enumerable.Range(1, 7);
        }

        /// <summary>
        /// Raises the <see cref="FontSelectionChanged"/> event.
        /// </summary>
        protected virtual void OnFontSelectionChanged()
        {
            FontSelectionEventArgs args = this.CreateFontSelectionEventArgs(FontSelectionChangedEvent);
            this.RaiseEvent(args);
        }

        /// <summary>
        /// Raises the <see cref="FontSizeSelectionChanged"/> event.
        /// </summary>
        protected virtual void OnFontSizeSelectionChanged()
        {
            FontSelectionEventArgs args = this.CreateFontSelectionEventArgs(FontSizeSelectionChangedEvent);
            this.RaiseEvent(args);
        }

        /// <summary>
        /// Raises the <see cref="FontColourSelected"/> event.
        /// </summary>
        protected virtual void OnFontColourSelected()
        {
            RoutedEventArgs args = new RoutedEventArgs(FontColourSelectedEvent);
            this.RaiseEvent(args);
        }

        /// <summary>
        /// Raises the <see cref="HighlightColourSelected"/> event.
        /// </summary>
        protected virtual void OnHighlightColourSelected()
        {
            RoutedEventArgs args = new RoutedEventArgs(HighlightColourSelectedEvent);
            this.RaiseEvent(args);
        }

        /// <summary>
        /// Raises the <see cref="StrikeThroughSelected"/> event.
        /// </summary>
        protected virtual void OnStrikeThroughSelected()
        {
            RoutedEventArgs args = new RoutedEventArgs(StrikeThroughSelectedEvent);
            this.RaiseEvent(args);
        }

        /// <summary>
        /// Raises the <see cref="AnchorInserting"/> event.
        /// </summary>
        protected virtual void OnAnchorInserting(AnchorEventArgs args)
        {
            args.RoutedEvent = AnchorInsertingEvent;
            this.RaiseEvent(args);
        }

        /// <summary>
        /// Raises the <see cref="AnchorInserted"/> event.
        /// </summary>
        protected virtual void OnAnchorInserted(string url, string linkText)
        {
            AnchorEventArgs args = new AnchorEventArgs(url, linkText, AnchorInsertedEvent);
            this.RaiseEvent(args);
        }

        /// <summary>
        /// Displays the colour picker, and returns the selected colour.
        /// </summary>
        /// <returns></returns>
        private Color? DisplayColourDialogue()
        {
            Color? c = null;
            ColorPickerDialog form = new ColorPickerDialog();
            if (form.ShowDialog() == true)
            {
                c = form.SelectedColor;
            }
            return c;
        }

        /// <summary>
        /// Displays the anchor dialogue, and gets the selected url.
        /// </summary>
        /// <returns></returns>
        private string DisplayAnchorDialogue(ref string linkText)
        {
            string url = string.Empty; 

            AnchorDialogue form = new AnchorDialogue(linkText);
            if (form.ShowDialog() == true)
            {
                url = form.Url;
                linkText = form.LinkText;
            }
            return url;
        }

        /// <summary>
        /// Creates new font selection event arguments.
        /// </summary>
        /// <returns></returns>
        private FontSelectionEventArgs CreateFontSelectionEventArgs(RoutedEvent sourceEvent)
        {
            FontFamily font = null;
            if (this.cboFontName.SelectedItem != null)
                font = (FontFamily)this.cboFontName.SelectedItem;

            int fontSize = 0;
            if (this.cboFontSize.SelectedItem != null)
                fontSize = (int)this.cboFontSize.SelectedItem;

            return new FontSelectionEventArgs(font, fontSize, sourceEvent);
        }

        private void cboFontName_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!this.IsLoaded) return;

            if (this.cboFontName.SelectedItem != null)
                this.OnFontSelectionChanged();
        }

        private void cboFontSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!this.IsLoaded) return;

            if (this.cboFontSize.SelectedItem != null)
                this.OnFontSizeSelectionChanged();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.cboFontName.SelectedItem = null;
            this.cboFontSize.SelectedItem = null;
        }

        private void btnFontColour_Click(object sender, RoutedEventArgs e)
        {
            Color? c = this.DisplayColourDialogue();
            if (c != null)
            {
                this.FontColour = c.Value;
                this.OnFontColourSelected();
            }
        }

        private void btnHighlightColour_Click(object sender, RoutedEventArgs e)
        {
            Color? c = this.DisplayColourDialogue();
            if (c != null)
            {
                this.HighlightColour = c.Value;
                this.OnHighlightColourSelected();
            }
        }

        private void btnStrikeThrough_Click(object sender, RoutedEventArgs e)
        {
            this.OnStrikeThroughSelected();
        }

        private void btnLink_Click(object sender, RoutedEventArgs e)
        {
            string url = string.Empty;
            string linkText = string.Empty;

            AnchorEventArgs args = new AnchorEventArgs(url, linkText);

            //raise the anchor inserting event
            this.OnAnchorInserting(args);

            //extract any updated values
            if (!string.IsNullOrEmpty(args.Url))
                url = args.Url;
            if (!string.IsNullOrEmpty(args.LinkText))
                linkText = args.LinkText;

            //display anchor dialogue
            url = this.DisplayAnchorDialogue(ref linkText);

            //raise the anchor inserted event
            if (!string.IsNullOrEmpty(url))
            {
                this.OnAnchorInserted(url, linkText);
            }
        }

    }
}
